﻿// Copyright 2013 Ronald Schlenker, www.technewlogic.de.
// 
// This file is part of Byond.
// 
// Byond is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 2 of the License, or
// (at your option) any later version.
// 
// Byond is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with Byond.  If not, see <http://www.gnu.org/licenses/>.

using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace Byond.Frontend.Controls
{
	[TemplatePart(Name = "PART_TextBox", Type = typeof(TextBox))]
	public class NumericTextBox : Control, INotifyPropertyChanged
	{
		static NumericTextBox()
		{
			DefaultStyleKeyProperty.OverrideMetadata(
				typeof(NumericTextBox),
				new FrameworkPropertyMetadata(typeof(NumericTextBox)));
		}

		#region InputText

		public static readonly DependencyProperty InputTextProperty =
			DependencyProperty.Register(
				"InputText", typeof(string), typeof(NumericTextBox),
				new FrameworkPropertyMetadata(
					string.Empty,
					FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
					(s, e) =>
					{
						var that = (NumericTextBox)s;
						that.OnPropertyChanged("DisplayText");
					},
					(s, e) =>
					{
						var that = (NumericTextBox)s;
						double d;
						if (double.TryParse(e.ToString(), out d))
						{
							if (that.Value != d)
								that.Value = d;
						}

						return that.Value.ToString();
					}));

		public string InputText
		{
			get { return (string)GetValue(InputTextProperty); }
			set { SetValue(InputTextProperty, value); }
		}

		#endregion

		#region Value

		public static readonly DependencyProperty ValueProperty =
			DependencyProperty.Register(
				"Value", typeof(double), typeof(NumericTextBox),
				new FrameworkPropertyMetadata(
					0d,
					FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
					(s, e) =>
					{
						if (e.OldValue == e.NewValue)
							return;

						var that = (NumericTextBox)s;
						that.InputText = e.NewValue.ToString();
						that.OnPropertyChanged("DisplayText");
					},
					(s, e) =>
					{
						var that = (NumericTextBox)s;
						var value = (double)e;
						return Math.Round(value, that.Digits);
					}));

		public double Value
		{
			get { return (double)GetValue(ValueProperty); }
			set { SetValue(ValueProperty, value); }
		}

		#endregion

		public string DisplayText { get { return Value + " " + Unit; } }

		private int _digits;
		public int Digits
		{
			get { return _digits; }
			set { _digits = value < 0 ? 0 : value > 15 ? 15 : value; }
		}

		public string Unit { get; set; }

		public override void OnApplyTemplate()
		{
			base.OnApplyTemplate();

			var textBox = Template.FindName("PART_TextBox", this) as TextBox;
			textBox.GotKeyboardFocus += (s, e) => textBox.SelectAll();
			textBox.KeyDown += (s, e) =>
			{
				if (e.Key == Key.Escape)
				{
					Keyboard.ClearFocus();
					textBox.Text = InputText;
				}
				else if (e.Key == Key.Enter)
					textBox.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
			};
		}

		#region INotifyPropertyChanged

		public event PropertyChangedEventHandler PropertyChanged;

		protected virtual void OnPropertyChanged(string propertyName)
		{
			var handler = PropertyChanged;
			if (handler != null)
				handler(this, new PropertyChangedEventArgs(propertyName));
		}

		#endregion
	}
}
